#ifndef LONGKEY_BASE_COMMAND_LINE_PARSER_H_
#define LONGKEY_BASE_COMMAND_LINE_PARSER_H_

#include <windows.h>
#include <atlstr.h>
#include <map>
#include <vector>
#include "../base/basictypes.h"
#include "../base/scoped_ptr.h"

namespace internal
{
	class CommandLineParserArgs;
}

class CommandLineParser
{
public:
	CommandLineParser();
	~CommandLineParser();

	// Parses the command line from a string.  Must include the program name (e.g.
	// foo.exe) as the first value in the command line.
	HRESULT ParseFromString(const wchar_t* command_line);

	// Parses the command line form argc/argv syntax.  Makes the assumption that
	// argv[0] is the program name (e.g. foo.exe).
	HRESULT ParseFromArgv(int argc, wchar_t** argv);

	// TODO: Name these methods "Required".
	// Gets the number of required switches in the parsed command line.
	int GetSwitchCount() const;

	// Returns the required switch at a particular index.
	HRESULT GetSwitchNameAtIndex(int index, CString* switch_name) const;

	// Returns true if a required switch with the name switch_name is found.
	bool HasSwitch(const CString& switch_name) const;

	// Returns the number of required arguments for required switch switch_name.
	HRESULT GetSwitchArgumentCount(const CString& switch_name,
		int* count) const;

	// Returns the value of a required switch argument at the specified offset.
	HRESULT GetSwitchArgumentValue(const CString& switch_name,
		int argument_index,
		CString* argument_value) const;

	// Functions that have the same functionality as the above functions,
	// except they operate on the optional switches.
	int GetOptionalSwitchCount() const;
	bool HasOptionalSwitch(const CString& switch_name) const;
	HRESULT GetOptionalSwitchNameAtIndex(int index, CString* switch_name) const;
	HRESULT GetOptionalSwitchArgumentCount(const CString& switch_name,
		int* count) const;
	HRESULT GetOptionalSwitchArgumentValue(
		const CString& switch_name,
		int argument_index,
		CString* argument_value) const;

private:
	bool IsSwitch(const CString& param) const;
	HRESULT StripSwitchNameFromArgv(const CString& param, CString* switch_name);
	bool IsOptionalSwitch(const CString& param) const;
	HRESULT StripOptionalSwitchNameFromArgv(const CString& param, CString* name);

	void Reset();

	HRESULT AddSwitch(const CString& switch_name);
	HRESULT AddSwitchArgument(const CString& switch_name,
		const CString& argument_value);
	HRESULT AddOptionalSwitch(const CString& switch_name);
	HRESULT AddOptionalSwitchArgument(const CString& switch_name,
		const CString& argument_value);

	scoped_ptr<internal::CommandLineParserArgs> required_args_;
	scoped_ptr<internal::CommandLineParserArgs> optional_args_;

	DISALLOW_EVIL_CONSTRUCTORS(CommandLineParser);
};

#endif	// LONGKEY_BASE_COMMAND_LINE_PARSER_H_